/**
 * @file   AbstractSimpleNode.h
 * @author Djuro Drljaca (djurodrljaca@gmail.com)
 * @date   2014-04-29
 * @brief  Base class for a simple DON node.
 *
 * Copyright 2014  Djuro Drljaca (djurodrljaca@gmail.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef DON_CORE_NODE_ABSTRACTSIMPLENODE_H
#define DON_CORE_NODE_ABSTRACTSIMPLENODE_H

#include <DON/Core/Node/AbstractNode.h>
#include <DON/Core/Node/AccessModifier.h>
#include <DON/Core/DataType/AbstractDataType.h>

namespace DON
{
namespace Core
{
namespace Packet
{

class RegistrationRequestPacket;
class RegistrationResponsePacket;
class GetPropertyValueRequestPacket;
class GetPropertyValueResponsePacket;

}

namespace Node
{

/**
 * @brief The AbstractSimpleNode class
 */
class LIBDONQT4CORESHARED_EXPORT AbstractSimpleNode : public AbstractNode
{
public:
    /**
     * @brief Constructor
     */
    AbstractSimpleNode();

    /**
     * @brief Destructor
     */
    virtual ~AbstractSimpleNode();

    /**
     * @brief Checks if this nodes parameters are valid
     * @retval true This nodes parameters are valid
     * @retval false This nodes parameters are not valid
     */
    virtual bool isValid() const;

protected:
    /**
     * @brief Get property count
     * @return Number of properties in the node
     *
     * @note Default implementation returns 0
     */
    virtual int getPropertyCount() const;

    /**
     * @brief Get property's data type
     * @param propertyId Selected property ID
     * @param[out] ok Error status output (true --> success, false --> error)
     * @return Property data type
     *
     * @note Default implementation returns an error
     */
    virtual DataType::DataType getPropertyDataType(const quint16 propertyId, bool *ok = NULL) const;

    /**
     * @brief Get property's access modifier
     * @param propertyId Selected property ID
     * @param[out] ok Error status output (true --> success, false --> error)
     * @return Property access modifier
     *
     * @note Default implementation returns an error
     */
    virtual AccessModifier getPropertyAccessModifier(const quint16 propertyId,
                                                     bool *ok = NULL) const;

    /**
     * @brief Get property's name
     * @param propertyId Selected property ID
     * @param[out] ok Error status output (true --> success, false --> error)
     * @return Property name
     *
     * @note Default implementation returns an error
     */
    virtual QString getPropertyName(const quint16 propertyId, bool *ok = NULL) const;

    /**
     * @brief Get property's value
     * @param propertyId Selected property ID
     * @param[out] ok Error status output (true --> success, false --> error)
     * @return Property value
     *
     * @note Default implementation returns an error
     */
    virtual const DataType::AbstractDataType * getPropertyValue(const quint16 propertyId,
                                                                bool *ok = NULL) const;

    /**
     * @brief Set property value
     * @param index Index of the property in the node property list
     * @param value New property value
     * @retval true Success
     * @retval false Error
     *
     * @note Default implementation returns an error
     */
    virtual bool setPropertyValue(const quint16 propertyId,
                                  const DataType::AbstractDataType &value);

    // TODO: add methods
    // TODO: add events

    /**
     * @brief Handle received packet
     * @param receivedPacket Received packet
     */
    void handleReceivedPacket(const Packet::GenericPacket &receivedPacket);

    /**
     * @brief Handle RegistrationRequest packet
     * @param packet RegistrationRequest packet
     *
     * @note Default implementation just ignores the packet.
     */
    virtual void handleReceivedRegistrationRequestPacket(
            const Packet::RegistrationRequestPacket &packet);

    /**
     * @brief Handle RegistrationResponse packet
     * @param packet RegistrationResponse packet
     *
     * @note Default implementation just ignores the packet.
     */
    virtual void handleReceivedRegistrationResponsePacket(
            const Packet::RegistrationResponsePacket &packet);

    /**
     * @brief Handle GetPropertyValueRequest packet
     * @param packet GetPropertyValueRequest packet
     *
     * @note Default implementation tries to read the nodes property value.
     */
    virtual void handleReceivedGetPropertyValueRequestPacket(
            const Packet::GetPropertyValueRequestPacket &packet);

    /**
     * @brief Handle GetPropertyValueResponse packet
     * @param receivedPacket Received packet
     *
     * @note Default implementation just ignores the packet.
     */
    virtual void handleReceivedGetPropertyValueResponsePacket(
            const Packet::GetPropertyValueResponsePacket &packet);

    /**
     * @brief Handle SetPropertyValueRequest packet
     * @param receivedPacket Received packet
     */
    virtual void handleReceivedSetPropertyValueRequestPacket(
            const Packet::GenericPacket &receivedPacket);

    /**
     * @brief Handle SetPropertyValueResponse packet
     * @param receivedPacket Received packet
     */
    virtual void handleReceivedSetPropertyValueResponsePacket(
            const Packet::GenericPacket &receivedPacket);

    /**
     * @brief Handle ExecuteMethod packet
     * @param receivedPacket Received packet
     */
    virtual void handleReceivedExecuteMethodRequestPacket(
            const Packet::GenericPacket &receivedPacket);

    /**
     * @brief Handle ExecuteMethod packet
     * @param receivedPacket Received packet
     */
    virtual void handleReceivedExecuteMethodResponsePacket(
            const Packet::GenericPacket &receivedPacket);

    /**
     * @brief Handle Event packet
     * @param receivedPacket Received packet
     */
    virtual void handleReceivedEventPacket(
            const Packet::GenericPacket &receivedPacket);

    /**
     * @brief Handle EventConfirmation packet
     * @param receivedPacket Received packet
     */
    virtual void handleReceivedEventConfirmationPacket(const Packet::GenericPacket &receivedPacket);

private:
    AbstractSimpleNode(const AbstractSimpleNode &other);
    AbstractSimpleNode & operator=(const AbstractSimpleNode &other);
};

}
}
}

#endif // DON_CORE_NODE_ABSTRACTSIMPLENODE_H
